package club.haomoon.boss.service.impl;

import club.haomoon.boss.service.IFileService;
import club.haomoon.boss.validate.base.FileCateValidate;
import club.haomoon.boss.validate.base.FileSearchValidate;
import club.haomoon.boss.vo.base.FileCategoryVo;
import club.haomoon.boss.vo.base.FileVo;
import club.haomoon.boss.validate.base.PageValidate;
import club.haomoon.core.common.PageResult;
import club.haomoon.core.config.GlobalConfig;
import club.haomoon.core.entity.file.FileCateData;
import club.haomoon.core.entity.file.FileData;
import club.haomoon.core.mapper.file.FileCateDataMapper;
import club.haomoon.core.mapper.file.FileDataMapper;
import club.haomoon.core.plugin.storage.StorageDriver;
import club.haomoon.core.util.*;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * -------------------------
 * @Description: 文件服务实现类
 * @Author: Wangjianwei
 * @Date: 2025/02/18 17:47
 * -------------------------
 */
@Service
public class FileServiceImpl implements IFileService {

    @Resource
    FileDataMapper fileDataMapper;

    @Resource
    FileCateDataMapper fileCateDataMapper;

    /**
     * 相册文件列表
     * @param pageValidate 分页参数
     * @param searchValidate 搜索参数
     * @return PageResult<AlbumVo>
     */
    @Override
    public PageResult<FileVo> fileList(PageValidate pageValidate, FileSearchValidate searchValidate) {
        Integer page  = pageValidate.getPage_no();
        Integer limit = pageValidate.getPage_size();

        QueryWrapper<FileData> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(FileData.class, info->
                    !info.getColumn().equals("aid") &&
                    !info.getColumn().equals("uid") &&
                    !info.getColumn().equals("delete_time"))
                .isNull("delete_time")
                .orderByDesc("id");

        if (StringUtils.isNotNull(searchValidate.getCid())) {
            queryWrapper.eq("cid", searchValidate.getCid());
        }

        fileDataMapper.setSearch(queryWrapper, searchValidate, new String[]{
                "=:type:int",
                "like:name@name:str",
                "=:source:int"
        });

        IPage<FileData> iPage = fileDataMapper.selectPage(new Page<>(page, limit), queryWrapper);

        String engine = ConfigUtil.get("storage", "default", "local");
        engine = engine.equals("") ? "local" : engine;

        List<FileVo> list = new ArrayList<>();
        for (FileData file : iPage.getRecords()) {
            FileVo vo = new FileVo();
            BeanUtils.copyProperties(file, vo);
            vo.setUrl(UrlUtil.toAdminAbsoluteUrl(file.getUri()));

            if (engine.equals("local")) {
                vo.setUri(GlobalConfig.adminPublicPrefix + "/" + file.getUri());
            } else {
                vo.setUri(file.getUri());
            }

            vo.setCreateTime(DateUtil.timestampToDate(file.getCreateTime()));
            vo.setUpdateTime(DateUtil.timestampToDate(file.getUpdateTime()));
            list.add(vo);
        }

        return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list);
    }

    /**
     * 文件重命名
     * @param id 文件ID
     * @param name 文件名称
     */
    @Override
    public void fileRename(Integer id, String name) {
        FileData file = fileDataMapper.selectOne(new QueryWrapper<FileData>()
                .select("id", "name")
                .eq("id", id)
                .isNull("delete_time"));

        Assert.notNull(file, "文件丢失！");

        file.setName(name);
        file.setUpdateTime(System.currentTimeMillis() / 1000);
        fileDataMapper.updateById(file);
    }

    /**
     * 文件移动
     *
     * @author Wangjw
     * @param ids 文件ID
     * @param cid 类目ID
     */
    @Override
    public void fileMove(List<Integer> ids, Integer cid) {
        List<FileData> files = fileDataMapper.selectList(new QueryWrapper<FileData>()
                .select("id", "name")
                .in("id", ids)
                .isNull("delete_time"));

        Assert.notNull(files, "文件丢失！");

        if (cid > 0) {
            Assert.notNull(fileCateDataMapper.selectOne(
                    new QueryWrapper<FileCateData>()
                            .eq("id", cid)
                            .isNull("delete_time")
            ), "类目已不存在！");
        }

        for (FileData file : files) {
            file.setCid(cid);
            file.setUpdateTime(System.currentTimeMillis() / 1000);
            fileDataMapper.updateById(file);
        }
    }

    /**
     * 文件新增
     *
     * @author Wangjw
     * @param params 文件信息参数
     */
    @Override
    public Integer fileAdd(Map<String, String> params) {
        String name = params.get("name");
        if (name.length() >= 100) {
            name = name.substring(0, 99);
        }

        FileData album = new FileData();
        album.setCid(Integer.parseInt(params.get("cid") == null ? "0" : params.get("cid")));
        album.setSourceId(Integer.parseInt(params.get("uid") == null ? "0" : params.get("uid")));
        album.setType(Integer.parseInt(params.get("type")));
        album.setName(name);
        album.setUri(params.get("url"));
        album.setCreateTime(System.currentTimeMillis() / 1000);
        album.setUpdateTime(System.currentTimeMillis() / 1000);
        fileDataMapper.insert(album);
        return album.getId();
    }

    /**
     * 相册文件删除
     *
     * @author Wangjw
     * @param ids 文件ID
     */
    @Override
    public void fileDel(List<Integer> ids) {
        List<FileData> files = fileDataMapper.selectList(new QueryWrapper<FileData>()
                .in("id", ids)
                .isNull("delete_time"));

        Assert.notNull(files, "文件丢失！");

        for (FileData file : files) {
            StorageDriver driver = new StorageDriver();
            driver.deleteFile(file.getUri());
            file.setDeleteTime(System.currentTimeMillis() / 1000);
            fileDataMapper.updateById(file);
        }
    }

    /**
     * 相册分类列表
     *
     * @param searchValidate 搜索参数
     * @return JSONArray
     */
    @Override
    public JSONObject cateList(FileSearchValidate searchValidate) {
        QueryWrapper<FileCateData> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(FileCateData.class, info->
                        !info.getColumn().equals("delete_time"))
                .isNull("delete_time")
                .orderByDesc("id");

        if (StringUtils.isNotNull(searchValidate.getType()) && searchValidate.getType() > 0) {
            queryWrapper.eq("type", searchValidate.getType());
        }

        if (StringUtils.isNotNull(searchValidate.getName()) && StringUtils.isNotEmpty(searchValidate.getName())) {
            queryWrapper.like("name", searchValidate.getName());
        }

        List<FileCateData> fileCateList = fileCateDataMapper.selectList(queryWrapper);

        List<FileCategoryVo> lists = new LinkedList<>();
        for (FileCateData fileCate : fileCateList) {
            FileCategoryVo vo = new FileCategoryVo();
            BeanUtils.copyProperties(fileCate, vo);

            vo.setCreateTime(DateUtil.timestampToDate(fileCate.getCreateTime()));
            vo.setUpdateTime(DateUtil.timestampToDate(fileCate.getUpdateTime()));
            lists.add(vo);
        }

        JSONArray jsonArray = JSONArray.parseArray(JSONArray.toJSONString(lists));

        JSONObject result = new JSONObject();

        result.put("lists", ListUtil.listToTree(jsonArray, "id", "pid", "children"));

        return result;
    }

    /**
     * 分类新增
     *
     * @author Wangjw
     * @param cateValidate 分类参数
     */
    @Override
    public void cateAdd(FileCateValidate cateValidate) {
        FileCateData albumCate = new FileCateData();
        albumCate.setType(cateValidate.getType());
        albumCate.setPid(cateValidate.getPid());
        albumCate.setName(cateValidate.getName());
        albumCate.setCreateTime(System.currentTimeMillis() / 1000);
        albumCate.setUpdateTime(System.currentTimeMillis() / 1000);
        fileCateDataMapper.insert(albumCate);
    }

    /**
     * 分类重命名
     *
     * @author Wangjw
     * @param id 分类ID
     * @param name 分类名称
     */
    @Override
    public void cateRename(Integer id, String name) {
        FileCateData fileCate = fileCateDataMapper.selectOne(
                new QueryWrapper<FileCateData>()
                        .select("id", "name")
                        .eq("id", id)
                        .isNull("delete_time"));

        Assert.notNull(fileCate, "分类已不存在！");

        fileCate.setName(name);
        fileCate.setUpdateTime(System.currentTimeMillis() / 1000);
        fileCateDataMapper.updateById(fileCate);
    }

    /**
     * 分类删除
     *
     * @author Wangjw
     * @param id 分类ID
     */
    @Override
    public void cateDel(Integer id) {
        FileCateData albumCate = fileCateDataMapper.selectOne(
                new QueryWrapper<FileCateData>()
                        .select("id", "name")
                        .eq("id", id)
                        .isNull("delete_time"));

        Assert.notNull(albumCate, "分类已不存在！");

        Assert.isNull(fileDataMapper.selectOne(new QueryWrapper<FileData>()
                .select("id", "cid", "name")
                .eq("cid", id)
                .isNull("delete_time")
                .last("limit 1")
            ), "当前分类正被使用中,不能删除！");

        albumCate.setDeleteTime(System.currentTimeMillis() / 1000);
        fileCateDataMapper.updateById(albumCate);
    }

}
